﻿using JESAI.Redis.Abstracts;
using JESAI.Redis.Enums;
using JESAI.Redis.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace JESAI.Redis.Builders
{
    public class ConnectionBuilder : IConnectionBuilder
    {
        /// <summary>
        /// 拆分的分隔符
        /// </summary>
        private const char SplitChar = ',';

        /// <summary>
        /// 相等
        /// </summary>
        private const char EqualChar = '=';
        /// <summary>
        /// 主节点名称 用于哨兵
        /// </summary>
        public string MasterName { get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        /// 密码
        /// </summary>
        public string Password { get; set; }
        /// <summary>
        /// 是否启用RESP3
        /// </summary>
        public bool RESP3 { get; set; }

        /// <summary>
        /// 数据存储库
        /// </summary>
        private int _dBIndex = 0;
        public int DBIndex
        {
            get
            {
                return _dBIndex;
            }
            set
            {
                if (value < 0 || value > 15)
                    throw new ArgumentOutOfRangeException(nameof(value), "数据库编号必须介于0-15之间");
                _dBIndex = value;
            }
        }

        /// <summary>
        /// 服务集群类型
        /// </summary>
        public ServerType ServerType { get; set; }

        /// <summary>
        /// 最大连接池大小
        /// </summary>
        public int MaxPoolSize { get; set; }

        /// <summary>
        /// 连接池大小
        /// </summary>
        public int PoolSize { get; set; }

        /// <summary>
        /// 连接超时时间
        /// </summary>
        public int TryGetRetryCount { get; set; }

        /// <summary>
        /// 连接超时时间
        /// </summary>
        public TimeSpan IdleTime { get; set; }

        /// <summary>
        /// 连接字符串数组
        /// </summary>
        public string[] ConnectionStringArray { get; set; }

        /// <summary>
        /// 连接超时时间
        /// </summary>
        public int TimeOut { get; set; }

        public ConnectionBuilder()
        {
            TimeOut = 3000;
            PoolSize = 10;
            MaxPoolSize = 100;
            TryGetRetryCount = 3;
        }

        /// <summary>
        /// 解析连接字符串
        /// </summary>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        internal static ConnectionBuilder Parse(string connectionString)
        {
            ConnectionBuilder builder = new ConnectionBuilder();
            builder = builder.ParseConnsction(connectionString);
            return builder;
        }

        public ConnectionBuilder ParseConnsction(string connectionString)
        {
            var configs = connectionString.Split(SplitChar);
            if (configs is not { Length: > 0 })
            {
                throw new ArgumentNullException(nameof(connectionString));
            }
            //连接地址
            var connection = new HashSet<string>();
            //遍历
            foreach (var itemEle in configs.Select(a => a.Trim()))
            {
                //判断是否是 主机地址
                if (itemEle.IndexOf(EqualChar) > 0)
                {
                    var ele = itemEle.Split(EqualChar);
                    switch (ele[0])
                    {
                        case "username":
                            UserName = ele[1];
                            break;
                        case "password":
                            Password = ele[1];
                            break;
                        case "servertype":
                            ServerType = (ServerType)ele[1].ToInt();
                            break;
                        case "mastername":
                            MasterName = ele[1];
                            break;
                        case "database":
                            DBIndex = ele[1].ToInt();
                            break;
                        case "poolsize":
                            PoolSize = ele[1].ToInt();
                            break;
                        case "maxpoolsize":
                            MaxPoolSize = ele[1].ToInt();
                            break;
                        case "timeout":
                            TimeOut = ele[1].ToInt();
                            break;
                        case "idletime":
                            IdleTime = TimeSpan.FromMilliseconds(ele[1].ToInt());
                            break;
                        case "resp3":
                            RESP3 = ele[1].ToBool();
                            break;
                    }
                }
                else
                {
                    connection.Add(itemEle);
                }

            }
            ConnectionStringArray = connection.ToArray();
            return this;
        }
    }
}
